package io.github.luons.mediator.core.exception;

import io.github.luons.mediator.core.spi.result.ResultCode;
import lombok.Data;

import java.io.PrintWriter;
import java.io.StringWriter;

@Data
public class ApiException extends RuntimeException {

    private Integer code;

    public ApiException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public ApiException(ResultCode resultEnum) {
        super(resultEnum.getName());
        this.code = resultEnum.getCode();
    }

    public ApiException(ResultCode dataCode, String message) {
        super(message);
        this.code = dataCode.getCode();
    }

    public ApiException(ResultCode dataCode, String message, Throwable cause) {
        super(message + " _ " + getMessage(cause), cause);
        this.code = dataCode.getCode();
    }

    public static ApiException asException(String message) {
        return new ApiException(500, message);
    }

    public static ApiException asException(ResultCode dataCode) {
        return new ApiException(dataCode);
    }

    public static ApiException asException(ResultCode dataCode, String message) {
        return new ApiException(dataCode, message);
    }

    public static ApiException asException(ResultCode dataCode, Throwable cause) {
        return asException(dataCode, dataCode.getName(), cause);
    }

    public static ApiException asException(ResultCode dataCode, String message, Throwable cause) {
        if (cause instanceof ApiException) {
            return (ApiException) cause;
        }
        return new ApiException(dataCode, message, cause);
    }

    private static String getMessage(Object obj) {
        if (obj == null) {
            return "";
        }
        if (obj instanceof Throwable) {
            StringWriter str = new StringWriter();
            PrintWriter pw = new PrintWriter(str);
            ((Throwable) obj).printStackTrace(pw);
            return str.toString();
        } else {
            return obj.toString();
        }
    }
}
